<?php
/**
 * OrganizationAccess model class file.
 *
 * @package   models
 * @since     1.0
 * @filesource
 */

/**
 * This is the model class for table "{{organization_access}}".
 * This is a DAO class which is used by DisorderController or other controllers
 * to operate data in database or return data in a specified format.
 *
 * The followings are the available columns in table '{{organization_access}}':
 * @property integer $id
 * @property integer $userId
 * @property integer $organizationId
 * @property integer $accessCreate
 * @property integer $accessView
 * @property integer $accessDownload
 * @property integer $accessUpdate
 * @property integer $accessDelete
 *
 * The followings are the available model relations:
 * @property Organization $organization - an Organization object related to OrganizationAccess object.
 * @property User $user - a User object related to the OrganizationAccess object.
 */
class OrganizationAccess extends CActiveRecord
{
	/**
	 * Returns the static model of the specified AR class.
	 * @return OrganizationAccess the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	/**
	 * Returns the table name related to this model class.
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return '{{organization_access}}';
	}

	/**
	 * Returns the validation rules.
	 * The rules will be used when requesting validation by call self.validate().
	 * Many class method will call self.validate(), eg: CActiveRecord.save().
	 * @return array validation rules for model attributes.
	 */
	public function rules()
	{
		return array(
		array('userId, organizationId, accessCreate, accessView, accessDownload, accessUpdate, accessDelete', 'required'),
		array('userId, organizationId, accessCreate, accessView, accessDownload, accessUpdate, accessDelete', 'numerical', 'integerOnly'=>true),
		// the organization id and user id combination should be unique
		array('organizationId','uniqueUserOrganization','on'=>'insert'),
		// The update access cannot be assigned unless the user has create access
		array('accessUpdate','validateUpdateWithoutCreate'),
		// The following rule is used by search().
		array('organizationId, accessCreate, accessView, accessDownload, accessUpdate, accessDelete', 'safe', 'on'=>'search'),
		);
	}

	/**
	 * Returns the relationship between this Model class and other Model class
	 * based on foreign key constraint between corresponding tables.
	 * The relationships involved in this application involves HAS_MANY, HAS_ONE, BELONGS_TO,
	 * please refer to Yii document for details.
	 * @return array relational rules.
	 */
	public function relations()
	{
		return array(
			// one organization access record is related to a organization.
			'organization' => array(self::BELONGS_TO, 'Organization', 'organizationId'),
			// one organization access record is related to a user.
			'user' => array(self::BELONGS_TO, 'User', 'userId'),
		);
	}

	/**
	 * Returns the labels for each column variables. 
	 * This will be used to render label on page.
	 * @return array customized attribute labels (name=>label)
	 */
	public function attributeLabels()
	{
		return array(
			'id' => 'ID',
			'userId' => 'User',
			'organizationId' => 'Organization',
			'accessCreate' => 'Access Create',
			'accessView' => 'Access View',
			'accessDownload' => 'Access Download',
			'accessUpdate' => 'Access Update',
			'accessDelete' => 'Access Delete',
		);
	}

	/**
	 * Retrieves a list of models based on the current search/filter conditions 
	 * declared in this function.
	 * @return CActiveDataProvider the data provider that can return the models 
	 * based on the search/filter conditions.
	 */
	public function search($userId)
	{
		$criteria=new CDbCriteria;

		$criteria->condition='userId='.$userId;
		$criteria->compare('organizationId',$this->organizationId);
		$criteria->compare('accessCreate',$this->accessCreate);
		$criteria->compare('accessView',$this->accessView);
		$criteria->compare('accessDownload',$this->accessDownload);
		$criteria->compare('accessUpdate',$this->accessUpdate);
		$criteria->compare('accessDelete',$this->accessDelete);

		return new CActiveDataProvider(get_class($this), array(
			'criteria'=>$criteria,
		));
	}

	/**
	 * Validate if the composite of userId and organizationId is unique when add a new 
	 * organization access.
	 * This is a Validator function and is used in declaration of validation rules.
	 * @param string $attribute
	 * @param mixed $params
	 */
	public function uniqueUserOrganization($attribute, $params) {
		if (empty($this->userId) || empty($this->organizationId)) {
			//if userId or organizationId is null, then avoid this validation.
			return;
		}
		$exists=self::model()->exists(
			array(
				'condition'=>"userId=:userId AND organizationId=:organizationId",
				'params'=>array(':userId'=>$this->userId,':organizationId'=>$this->organizationId),				
			)
		);
		if ($exists)
		$this->addError('organizationId', 'Access to this Organization has been difined!');
	}

	/**
	 * Get organization access record by a given pair of user id and organization id.
	 * @param int $userId
	 * @param int $organizationId
	 * @return OrganizationAccess the OrganizationAccess object for specified user and organization.
	 */
	public static function findByUserOrganization($userId, $organizationId){
		return self::model()->find(
			array(
				'condition'=>"userId=:userId AND organizationId=:organizationId",
				'params'=>array(':userId'=>$userId,':organizationId'=>$organizationId),				
			)
		);
	}
	
	
	/**
	 * Validate if the "update" access is granted without "create".
	 * This is a validation function to avoid admin grant "Update" access right to
	 * a user, but not grant "Create" access right to a user when admin create or 
	 * update organization access for a user.
	 * @param string $attribute
	 * @param mixed $params
	 */
	public function validateUpdateWithoutCreate($attribute, $params) {
		if ($this->accessUpdate && !$this->accessCreate)
		$this->addError('accessUpdate', 'The user should be granted with "create" access if "update" is granted!');		
	}

	
	/**
	 * Check if current login user has "View" access to the specified organization. 
	 * Used in access control of Yii framework. Configured in the database table rules.
	 * @param int $organizationId
	 * @return boolean true if the check is successful, false otherwise
	 */
	public static function checkAccessView($organizationId) {
		if(Yii::app()->user->checkAccess('admin')){
			return true;
		}
		$access=OrganizationAccess::findByUserOrganization(Yii::app()->user->id,$organizationId);
		if($access){
			return $access->accessView==1?true:false;
		}else{
			$user=User::getCurrentUser();
			return $user->globalView==1?true:false;
		}
	}

	
	/**
	 * Check if current login user has "Create" access to the specified organization. 
	 * Used in access control of Yii framework. Configured in the database table rules.
	 * @param int $organizationId
	 * @return boolean true if the check is successful, false otherwise
	 */
	public static function checkAccessCreate($organizationId) {
		if(Yii::app()->user->checkAccess('admin')){
			return true;
		}
		$access=OrganizationAccess::findByUserOrganization(Yii::app()->user->id,$organizationId);
		if($access){
			return $access->accessCreate==1?true:false;
		}else{
			$user=User::getCurrentUser();
			return $user->globalCreate==1?true:false;
		}
	}

	
	/**
	 * Check if current login user has "Update" access to the specified organization. 
	 * Used in access control of Yii framework. Configured in the database table rules.
	 * @param int $organizationId
	 * @return boolean true if the check is successful, false otherwise
	 */
	public static function checkAccessUpdate($organizationId) {
		if(Yii::app()->user->checkAccess('admin')){
			return true;
		}
		$access=self::findByUserOrganization(Yii::app()->user->id,$organizationId);
		if($access){
			return $access->accessUpdate==1?true:false;
		}else{
			$user=User::getCurrentUser();
			return $user->globalUpdate==1?true:false;
		}
	}

	
	/**
	 * Check if current login user has "Download" access to the specified organization. 
	 * Used in access control of Yii framework. Configured in the database table rules.
	 * @param int $organizationId
	 * @return boolean true if the check is successful, false otherwise
	 */
	public static function checkAccessDownload($organizationId) {
		if(Yii::app()->user->checkAccess('admin')){
			return true;
		}
		$access=self::findByUserOrganization(Yii::app()->user->id,$organizationId);
		if($access){
			return $access->accessDownload==1?true:false;
		}else{
			$user=User::getCurrentUser();
			return $user->globalDownload==1?true:false;
		}
	}

	/**
	 * Check if current login user has "Delete" access to the specified organization. 
	 * Used in access control of Yii framework. Configured in the database table rules.
	 * @param int $organizationId
	 * @return boolean true if the check is successful, false otherwise
	 */
	public static function checkAccessDelete($organizationId) {
		if(Yii::app()->user->checkAccess('admin')){
			return true;
		}
		$access=self::findByUserOrganization(Yii::app()->user->id,$organizationId);
		if($access){
			return $access->accessDelete==1?true:false;
		}else{
			$user=User::getCurrentUser();
			return $user->globalDelete==1?true:false;
		}
	}
}